#ifndef _GERO_H_
#define _GERO_H_
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>

#include <libspe2.h>
#include <pthread.h>
#include <altivec.h>
#include <ppu_intrinsics.h>
#include <vec_types.h>

#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/custom.h>
#include <caml/callback.h>
#include <caml/fail.h>
#include <caml/bigarray.h>
#include <time.h>
#include <simdmath.h>
#include <simdmath/fmaf4.h>

#define MAX_SPE 6
#define f32_zero   (vector float ) vec_ctf(vec_splat_s32(0x00),0)
#define f32_un   (vector float ) vec_ctf(vec_splat_s32(0x01),0)

#define LOAD_REGISTER(  V, N, O, T1, T2, S )  V = vec_ld( (4*N + O)*vec_step(T1)*sizeof(T2), (T2*)S )
//#define LOAD_REGISTER(  V, N, O, T1, T2, S )   V = vec_perm(vec_ld((4*N+O)*sizeof(T2), S), vec_ld((4*N+O)*sizeof(T2)+16, S), vec_lvsl((4*N+O)*sizeof(T2), S))
#define ALLOC_RESULT_ARRAY(SIZE, T1) arg.result = (void*)memalign( 16, ((SIZE*sizeof(T1)  & ~63 ) + 64 ))
#define RESULTAT( V, I, J, T )           *( (T*)(V) + (4*(I) + J)) 

#define EVAL_VECTOR_SIZE(T1, T2) nb_iter = (((arg->size)*sizeof(T2) & ~63 ) + 64 ) / ((vec_step(T1) * sizeof(T2) * 4))

/**********Context and threads******************/

void *ppu_pthread_function(void *arg);
value gero_pthread_create(value v);
value gero_join(value v);

value gero_spe_context_destroy(value v);
value gero_spe_context_create(void);
value gero_spe_count_usable_spes(void);
value gero_spe_count_physical_spes(void);
value gero_spe_context_run(value ctx);
value gero_spe_image_open(value spe_prog);

/*******************  DMA  *********************/


typedef struct _control_block_4v{
	unsigned long long vec1_addr;
	unsigned long long vec2_addr;
	unsigned long long vec3_addr;
	unsigned long long res_addr;
	unsigned int size;
	unsigned char pad[12];
}CB_4V;

typedef struct pthread_data{
	spe_context_ptr_t spe_ctx;
	pthread_t pthread;
	unsigned int entry;
	void* argp;
}ppu_pthread_data_t;

/*************** Mathematiques *****************/
value gero_fmaf4 (value x, value y, value z);
value gero_fmaf4_spu(value x, value y, value z, value ctx);
value gero_load_fmaf4_spu(value ctx);

typedef struct av_argument_t GERO_ARGUMENTS;
struct av_argument_t
{
	void*  vector1; // __attribute__ ((aligned(128)));   /*< Premier argument vectoriel.   */
	void*  vector2; //  __attribute__ ((aligned(128)));    /*< Deuxieme argument vectoriel.  */
	void*  vector3; // __attribute__ ((aligned(128)));    /*< Troisieme argument vectoriel. */
	void*  result; //  __attribute__ ((aligned(128)));    /*< Resultat vectoriel.           */
	long   size;      /*< Taille des arguments.         */
};

//uint32_t entry;// = SPE_DEFAULT_ENTRY;
uint32_t nbspe;


#endif  
